package com.hk.web.controller.api;

import com.hk.commons.JsonResult;
import com.hk.commons.ProcessAPI;
import com.hk.commons.ResultCode;
import com.hk.commons.domain.service.JsonService;
import com.hk.commons.domain.service.UploadService;
import com.hk.commons.enums.UploadFiLeType;
import com.hk.commons.enums.UploadStatus;
import com.hk.web.controller.Routes;
import com.hk.web.domain.entity.UploadFile;
import com.hk.web.domain.lifeCycle.repository.UploadFileRepository;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.UUID;

/**
 * Created by Antinomy on 16/12/14.
 */

@RestController
public class UploadAPIController extends APIController {

    @Value("${qiniu.bucket.image.dns}")
    private String imageUrl;

    @Value("${qiniu.bucket.image}")
    private String image_bucket;

    @Value("${qiniu.bucket.contract.dns}")
    private String contractUrl;

    @Value("${qiniu.bucket.contract}")
    private String contract_bucket;

    @Value("${qiniu.ACCESS_KEY}")
    private String access_key;

    @Value("${qiniu.SECRET_KEY}")
    private String secret_key;

    @Autowired
    private UploadFileRepository uploadFileRepo;

    private Logger logger = LoggerFactory.getLogger(UploadAPIController.class);

    @RequestMapping(value = Routes.UPLOAD, method = RequestMethod.POST)
    @ResponseBody
    public HashMap upload(HttpServletRequest request,@RequestParam("upload_file") MultipartFile uploadFile,
                          @RequestParam(value = "file_md5",required = false)String file_md5) {

        ProcessAPI api = (jsonResult, validate) -> {
            UploadService uploadService = new UploadService(access_key, secret_key);

            UploadFile uploadEntity = null;

//            String file_md5 = request.getParameter("file_md5");
            logger.info("file_md5 :{}",file_md5);

            if(StringUtils.isNoneBlank(file_md5)){
                uploadEntity = uploadFileRepo.findFirst1ByMd5AndTypeAndStatus(file_md5, UploadFiLeType.IMAGE,UploadStatus.DONE);
            }

            if (uploadEntity == null) {
                String uuid = UUID.randomUUID().toString();
                String uploadedFileName = uuid + ".png";

                uploadEntity = createUploadEntity(uuid, UploadFiLeType.IMAGE,file_md5);

                String uploadResp = uploadService.uploadFile(image_bucket, uploadedFileName, uploadFile.getBytes());

                uploadEntity = updateRespToEntity(uploadResp, uploadFile.getOriginalFilename(),imageUrl, uploadEntity, jsonResult);
            }


            jsonResult.result = uploadEntity.getUrl();
        };

        JsonResult jsonResult = api.process(request);

        HashMap result = renderResult(jsonResult,null);

        return result;
    }

    @RequestMapping(value = Routes.UPLOAD_CONTRACT, method = RequestMethod.POST)
    @ResponseBody
    public HashMap uploadContract(HttpServletRequest request,
                                  @RequestParam("upload_file") MultipartFile uploadFile,
                                  @RequestParam("contract_id") String contract_file) {
        ProcessAPI api = (jsonResult, validate) -> {
            UploadService uploadService = new UploadService(access_key, secret_key);

            UploadFile uploadEntity = uploadFileRepo.findFirst1ByNameAndTypeAndStatus(contract_file, UploadFiLeType.CONTRACT, UploadStatus.DONE);

            if (uploadEntity == null) {
                String uuid = UUID.randomUUID().toString();
                uploadEntity = createUploadEntity(uuid, UploadFiLeType.CONTRACT, null);

                String uploadResp = uploadService.uploadFile(contract_bucket, contract_file, uploadFile.getBytes());

                uploadEntity = updateRespToEntity(uploadResp, contract_file, contractUrl, uploadEntity, jsonResult);
            }

            jsonResult.result = uploadEntity.getUrl();
        };

        JsonResult jsonResult = api.process(request);

        HashMap result = renderResult(jsonResult,contract_file);

        return result;
    }

    private UploadFile createUploadEntity(String uuid, UploadFiLeType fiLeType,String md5) {
        UploadFile uploadEntity = new UploadFile();
        uploadEntity.setType(fiLeType);
        uploadEntity.setUuid(uuid);
        uploadEntity.setMd5(md5);
        uploadEntity = uploadFileRepo.saveAndFlush(uploadEntity);
        return uploadEntity;
    }

    private HashMap renderResult(JsonResult jsonResult,String contract_id) {
        Boolean excuteResult = jsonResult.resultCode.equals(ResultCode.SUCC.getCode());

        HashMap result = new HashMap();
        result.put("success", excuteResult);
        result.put("msg", jsonResult.msg);
        result.put("file_path", jsonResult.result);

        if(StringUtils.isNotBlank(contract_id))
            result.put("contract_id", contract_id);

        return result;
    }

    private UploadFile updateRespToEntity(String uploadResp, String originalFilename,String dnsUrl, UploadFile uploadEntity, JsonResult jsonResult) {
        String hash = JsonService.readValue(uploadResp, "hash");
        String key = JsonService.readValue(uploadResp, "key");
        String url = dnsUrl + key;
        uploadEntity.setRespMsg(uploadResp);

        if (StringUtils.isNoneBlank(hash)) {
            // e.g. {"hash":"Fp_PFasnLUtYTmDbocBw7riqdvw6","key":"media.png"}
            uploadEntity.setName(originalFilename);
            uploadEntity.setHash(hash);
            uploadEntity.setUrl(url);
            uploadEntity.setStatus(UploadStatus.DONE);
        } else {
            String error = JsonService.readValue(uploadResp, "error");

            if (StringUtils.isNoneBlank(error)) {
                jsonResult.resultCode = ResultCode.PARAM_ERROR.getCode();
                jsonResult.msg = error;

                uploadEntity.setStatus(UploadStatus.FAILED);
            }
        }

        uploadEntity = uploadFileRepo.saveAndFlush(uploadEntity);
        return uploadEntity;
    }
}
